#include "FontManager.h"

CFontManager::CFontManager()
{
	m_pDev = NULL;
	m_bInitialized = false;
	m_pFonts.clear();
	m_pQueuedText.clear();
	m_szDebug = "Debug Mode";
	m_hrError = S_OK;
}

CFontManager::~CFontManager(void)
{
	Shutdown();
}

CFontManager* CFontManager::GetInstance(void)
{
	static CFontManager _pInstance;
	return &_pInstance;
}

bool CFontManager::Initialize(IDirect3DDevice9* _pDev)
{
	if(m_bInitialized)
		return false;

	if(!_pDev)
	{
		MessageBoxA(NULL, "Failed Initialization: Lost Device.", "Font Manager Error", MB_OK);
		return false;
	}

	m_pDev = _pDev;
	m_pFonts.clear();

	m_hrError = D3DXCreateSprite(_pDev, &m_pFontSurface);
	
	if(S_OK != m_hrError)
	{
		m_pFontSurface = NULL;
		MessageBoxA(NULL, "Failed To Create Font Surface", "Font Manager Error", MB_OK);
	}

	AddFont();

	m_bInitialized = true;
	return true;
}

bool CFontManager::Shutdown(void)
{
	if(!m_bInitialized)
		return false;

	map<PhAssetID, tFont>::iterator _FontIter = m_pFonts.begin();
	for( ; _FontIter != m_pFonts.begin(); ++_FontIter)
	{
		if(_FontIter->second.m_pFont)
			_FontIter->second.m_pFont->Release();
		
		_FontIter->second.m_pFont = NULL;
	}

	if(m_pFontSurface)
		m_pFontSurface->Release();

	m_pFonts.clear();
	m_pQueuedText.clear();
	m_szDebug = "Debug Mode";
	m_hrError = S_OK;
	m_pDev = NULL;
	m_bInitialized = false;
	return false;
}

bool CFontManager::Reload(void)
{
	if(!m_bInitialized)
		return false;

	map<PhAssetID, tFont>::iterator _pFontIter = m_pFonts.begin();
	for( ; _pFontIter != m_pFonts.end(); ++_pFontIter)
	{
		if(_pFontIter->second.m_pFont)
		{
			_pFontIter->second.m_pFont->Release();
			
			m_hrError = D3DXCreateFont(m_pDev, _pFontIter->second.m_phHeight, _pFontIter->second.m_phWidth, _pFontIter->second.m_phWidth, _pFontIter->second.m_eWeight, _pFontIter->second.m_bItalics, _pFontIter->second.m_eCharSet, _pFontIter->second.m_ePrecision, _pFontIter->second.m_eQuality, _pFontIter->second.m_ePitch | _pFontIter->second.m_eFamily, _pFontIter->second.m_szFaceName.c_str(), &_pFontIter->second.m_pFont);

			// Failed to load Font
			if(S_OK != m_hrError)
			{
				// Safe release _pFont if it was initialized in any way
				if(_pFontIter->second.m_pFont)
					_pFontIter->second.m_pFont->Release();
				_pFontIter->second.m_pFont = NULL;

				string _szError = "Failed To Reload Font: " + _pFontIter->second.m_szFaceName;
				MessageBoxA(NULL, _szError.c_str(), "Font Manager Error", MB_OK);
				return false;
			}
		}
	}

	if(m_pFontSurface)
		m_pFontSurface->Release();

	m_hrError = D3DXCreateSprite(m_pDev, &m_pFontSurface);
	if(S_OK != m_hrError)
		m_pFontSurface = NULL;

	return true;
}

PhAssetID CFontManager::AddFont(string _szFaceName, PhUInt8 _phHeight, PhUInt8 _phWidth, EFontWeight _eWeight, 
			PhUInt8 _phMipLevel, bool _bItalics, EFontCharSet _eCharSet, EFontPrecision _ePrecision, 
			EFontQuality _eQuality, EFontPitch _ePitch, EFontFamiy _eFamily)
{
	
	if(!m_pDev)
	{
		return PH_INVALID_ASSET_ID;
	}

	ID3DXFont* _pFont = NULL;
	m_hrError = D3DXCreateFont(m_pDev, _phHeight, _phWidth, _phWidth, _eWeight, _bItalics, _eCharSet, _ePrecision, _eQuality, _ePitch | _eFamily, _szFaceName.c_str(), &_pFont);

	// Failed to load Font
	if(S_OK != m_hrError)
	{
		// Safe release _pFont if it was initialized in any way
		if(_pFont)
			_pFont->Release();
		_pFont = NULL;

		MessageBoxA(NULL, "Failed To Add Font.", "Font Manager Error", MB_OK);
		return PH_INVALID_ASSET_ID;
	}

	int _nFaceNameLength = _szFaceName.length();
	map<PhAssetID, tFont>::iterator _pFontIter = m_pFonts.begin();
	
	// Duplicate Check
	for( ; _pFontIter != m_pFonts.end(); ++_pFontIter)
	{
		if(_pFontIter->second.m_szFaceName.length() == _nFaceNameLength)
		{
			if(!strcmp(_pFontIter->second.m_szFaceName.c_str(), _szFaceName.c_str()) == 0)
			{
				string _szError = "Duplicate Font Found: " + _szFaceName;
				MessageBoxA(NULL, _szError.c_str(), "Font Manager Error", MB_OK);
				return PH_INVALID_ASSET_ID;
			}
		}
	}

	// Find a unique ID
	PhAssetID _phID = 0;
	_pFontIter = m_pFonts.begin();
	for( ; _pFontIter != m_pFonts.end(); ++_pFontIter)
	{
		if(_pFontIter->first == _phID)
			++_phID;
		else
			break;
	}

	tFont _tNewFont;
	_tNewFont.m_pFont = _pFont;
	_tNewFont.m_phID = _phID;
	_tNewFont.m_szFaceName = _szFaceName;
	_tNewFont.m_phHeight = _phHeight;
	_tNewFont.m_phWidth = _phWidth;
	_tNewFont.m_eWeight = _eWeight;
	_tNewFont.m_phMipLevel = _phMipLevel;
	_tNewFont.m_bItalics = _bItalics;
	_tNewFont.m_eCharSet = _eCharSet;
	_tNewFont.m_ePrecision = _ePrecision;
	_tNewFont.m_eQuality = _eQuality;
	_tNewFont.m_ePitch = _ePitch;
	_tNewFont.m_eFamily = _eFamily;

	m_pFonts[_phID] = _tNewFont;
	return _phID;
}

ID3DXFont* CFontManager::GetFont(PhAssetID _phID)
{
	if(PH_INVALID_ASSET_ID == _phID)
		return m_pFonts[PH_FONT_ARIAL_ID].m_pFont;

	if(m_pFonts.find(_phID) != m_pFonts.end())
		return m_pFonts[_phID].m_pFont;

	return m_pFonts[PH_FONT_ARIAL_ID].m_pFont;
}

bool CFontManager::QueueText(string _szText, PhInt _phCount, float _fTop, float _fLeft, float _fBottom, float _fRight, DWORD _dwFormat, D3DCOLOR _Color)
{
	PhInt _nTextLength = _szText.length();	
	if(_nTextLength == 0 || _nTextLength < _phCount)
		return false;

	PhAssetID _phID = 0;
	bool _bReuse = false;
	map<PhAssetID, tQueuedText>::iterator _pQueuedIter = m_pQueuedText.begin();
	for( ; _pQueuedIter != m_pQueuedText.end(); ++_pQueuedIter)
	{
		if(_pQueuedIter->second.m_bAlive)
		{
			++_phID;
			_bReuse = true;
		}
		else
			break;
	}

	if(_bReuse)
	{
		m_pQueuedText[_phID].m_bAlive = true;
		m_pQueuedText[_phID].m_szText = _szText;
		m_pQueuedText[_phID].m_phCount = _phCount;
		m_pQueuedText[_phID].m_dwFormat = _dwFormat;
		m_pQueuedText[_phID].m_phColor = _Color;

		m_pQueuedText[_phID].m_rRect.top = (LONG)_fTop;
		m_pQueuedText[_phID].m_rRect.left = (LONG)_fLeft;
		m_pQueuedText[_phID].m_rRect.bottom = (LONG)_fBottom;
		m_pQueuedText[_phID].m_rRect.right = (LONG)_fRight;
		
		if(_fBottom == 0.0f && _fRight == 0)
			m_pQueuedText[_phID].m_bCalcRect = true;

		return true;
	}

	tQueuedText _tNewText;
	_tNewText.m_bAlive = true;
	_tNewText.m_szText = _szText;
	_tNewText.m_phCount = _phCount;
	_tNewText.m_dwFormat = _dwFormat;
	_tNewText.m_phColor = _Color;

	_tNewText.m_rRect.top = (LONG)_fTop;
	_tNewText.m_rRect.left = (LONG)_fLeft;
	_tNewText.m_rRect.bottom = (LONG)_fBottom;
	_tNewText.m_rRect.right = (LONG)_fRight;

	if(_fBottom == 0.0f && _fRight == 0)
		_tNewText.m_bCalcRect = true;

	m_pQueuedText[_phID] = _tNewText;
	return true;
}

tQueuedText* CFontManager::GetQueuedText(void)
{
	map<PhAssetID, tQueuedText>::iterator _pQueuedIter = m_pQueuedText.begin();
	for(; _pQueuedIter != m_pQueuedText.end(); ++_pQueuedIter)
	{
		if(_pQueuedIter->second.m_bAlive)
		{
			_pQueuedIter->second.m_bAlive = false;
			return &_pQueuedIter->second;
		}
	}

	return NULL;
}
